package com.tiancheng.trade.order.util.helper;

import com.tiancheng.trade.order.enums.OperateCodeEnum;
import com.tiancheng.trade.order.enums.OrderSceneEnum;
import com.tiancheng.trade.order.enums.OrderSourceEnum;
import com.tiancheng.trade.order.util.CommonUtil;
import com.tiancheng.trade.commom.core.utils.DateTimeUtil;
import com.tiancheng.trade.order.util.EnumUtil;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 订单编号生成
 *
 * @author kellen
 * @date 2024/2/28
 */
@Component
public class OrderIdHelper {

    @Resource
    private RedissonClient redissonClient;

    /**
     * 获取主订单号
     *
     * @param orderScene
     * @param orderSource
     * @param uid
     * @param isTest
     * @return
     */
    public String get(String orderScene, String orderSource, String uid, Boolean isTest) {
        String uidHashCode = String.valueOf(Math.abs(uid.hashCode()));
        String uidEnd = uidHashCode.substring(uidHashCode.length() - 4);

        // 同一个用户，按照秒级增长
        String incrTime = DateTimeUtil.format(LocalDateTime.now(), "yyMMddHH");
        String incrKey = new StringBuilder().append(OrderSceneEnum.valueOf(orderScene).getCode()).
                append(String.format("%02d", Integer.valueOf(orderSource).intValue())).
                append(isTest.booleanValue() ? "1" : "0").append(incrTime).append(uidEnd).toString();

        RAtomicLong rAtomicLong = redissonClient.getAtomicLong(incrKey);
        long incr = rAtomicLong.incrementAndGet();

        StringBuilder orderId = new StringBuilder();

        // ******** todo 临时解决老版本APP根据订单号判断问题
        orderId.append(orderSource);
        // ********

        orderId.append(OrderSceneEnum.valueOf(orderScene).getCode()).
                append(String.format("%02d", Integer.valueOf(orderSource).intValue())).
                append(isTest.booleanValue() ? "1" : "0").append(incrTime).append(uidEnd).
                append(String.format("%02d", incr));

        // 如果是当天第一个取号，就给key添加隔天失效时间
        if (incr == 1) {
            rAtomicLong.expireAsync(1, TimeUnit.HOURS);
        }
        return orderId.toString();
    }

    /**
     * 获取子订单号列表
     *
     * @param orderId
     * @param nums
     * @return
     */
    public List<String> getSub(String orderId, int nums) {
        List<String> subOrderIds = new ArrayList<>();
        for (int i = 1; i <= nums; i++) {
            subOrderIds.add(new StringBuilder().append(orderId).append(String.format("%02d", i)).toString());
        }
        return subOrderIds;
    }

    /**
     * 获取支付单号
     *
     * @param uid
     * @return
     */
    public String getPaymentId(String uid) {
//        long id = (LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli() << 12) | Math.abs(uid.hashCode()) | CommonUtil.getRandom(10, 10000000);
        StringBuilder paymentId = new StringBuilder();
        return paymentId.append(OperateCodeEnum.order_payment.getCode()).append(getGeneralId(uid)).toString();
    }

    /**
     * 订单号列表获取唯一编号
     *
     * @param uid
     * @param orderId
     * @param payWay
     * @return
     */
    public String getUniqueId(String uid, String orderId, String payWay,String payScene) {
        StringBuilder builder = new StringBuilder(uid);
        if(StringUtils.isNotEmpty(payScene)){
            return builder.append("_").append(Math.abs(orderId.hashCode())).append("_").append(payWay).append("_").append(payScene.toLowerCase()).toString();
        }else{
            return builder.append("_").append(Math.abs(orderId.hashCode())).append("_").append(payWay.toLowerCase()).toString();
        }
    }


    /**
     * 订单号列表获取唯一编号
     *
     * @param uid
     * @param orderIds 订单号集合
     * @param payWay
     * @return
     */
    public String getUniqueIdByOrderIds(String uid, List<String> orderIds, String payWay,String payScene,String batchId) {
        StringBuilder builder = new StringBuilder(uid);
        if(CollectionUtils.isNotEmpty(orderIds)){
            Collections.sort(orderIds);
        }
        final String orderIdsString = StringUtils.isEmpty(batchId)?String.join("", orderIds):batchId;
        if(StringUtils.isNotEmpty(payScene)){
            return builder.append("_").append(Math.abs(orderIdsString.hashCode())).append("_").append(payWay).append("_").append(payScene.toLowerCase()).toString();
        }else{
            return builder.append("_").append(Math.abs(orderIdsString.hashCode())).append("_").append(payWay.toLowerCase()).toString();
        }
    }

    /**
     * 获取退款单号
     *
     * @param uid
     * @return
     */
    public String getRefund(String uid) {
        long id = (LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli() << 12) | Math.abs(uid.hashCode()) | CommonUtil.getRandom(10, 10000000);
        StringBuilder paymentId = new StringBuilder();
        return paymentId.append(OperateCodeEnum.refund.getCode()).append(id).toString();
    }

    /**
     * 获取退款单号
     * todo 临时解决老版本APP根据编号判断业务场景
     *
     * @param uid
     * @return
     */
    public String getRefund(String orderSource, String uid) {
//        long id = (LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli() << 12) | Math.abs(uid.hashCode()) | CommonUtil.getRandom(10, 10000000);
        StringBuilder paymentId = new StringBuilder();
        return paymentId.append(EnumUtil.getEnumByCode(OrderSourceEnum.class, orderSource).code()).
                append(OperateCodeEnum.refund.getCode()).append(getGeneralId(uid)).toString();
    }

    /**
     * 获取退款支付单号
     *
     * @param uid
     * @return
     */
    public String getRefundPaymentId(String uid) {
//        long id = (LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli() << 12) | Math.abs(uid.hashCode()) | CommonUtil.getRandom(10, 10000000);
        StringBuilder paymentId = new StringBuilder();
        return paymentId.append(OperateCodeEnum.refund_payment.getCode()).append(getGeneralId(uid)).toString();
    }

    /**
     * 获取退款支付单号
     * todo 临时解决老版本APP根据编号判断业务场景
     *
     * @param uid
     * @return
     */
    public String getRefundPaymentId(String orderSource, String uid) {
        StringBuilder paymentId = new StringBuilder();
        return paymentId.append(EnumUtil.getEnumByCode(OrderSourceEnum.class, orderSource).code()).
                append(OperateCodeEnum.refund_payment.getCode()).append(getGeneralId(uid)).toString();
    }

    /**
     * 获取订单核销单号
     * @param uid
     * @return
     */
    public String getVerificationId(String uid) {
        StringBuilder paymentId = new StringBuilder();
        return paymentId.append(OperateCodeEnum.verification.getCode()).append(getGeneralId(uid)).toString();
    }

    /**
     * 获取用户开卡订单号
     * @param uid
     * @return
     */
    public String getBindingBankCardId(String uid,OperateCodeEnum operateCodeEnum) {
        StringBuilder paymentId = new StringBuilder();
        return paymentId.append(operateCodeEnum.getCode()).append(getGeneralId(uid)).toString();
    }

    /**
     * 获取用户查询银行卡列表接口
     * @param uid
     * @return
     */
    public String getQueryBankListId(String uid) {
        StringBuilder paymentId = new StringBuilder();
        return paymentId.append(OperateCodeEnum.QUERY_BANK_LIST.getCode()).append(getGeneralId(uid)).toString();
    }

    /**
     * 获取二维码支付单号
     *
     * @param uid
     * @return
     */
    public String getQrOrderId(String uid) {
//        long id = (LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli() << 12) | Math.abs(uid.hashCode()) | CommonUtil.getRandom(10, 10000000);
        return new StringBuilder().append(OperateCodeEnum.QR_ORDER.getCode()).append(getGeneralId(uid)).toString();
    }

    /**
     * 获取批次支付单号
     *
     * @param uid
     * @return
     */
    public String getBatchOrderId(String uid,Integer orderNum) {
//        long id = (LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli() << 12) | Math.abs(uid.hashCode()) | CommonUtil.getRandom(10, 10000000);
        return new StringBuilder().append(OperateCodeEnum.BATCH_ORDER.getCode()).append(orderNum).append(getGeneralId(uid)).toString();
    }


    /**
     * 获取账单号
     *
     * @param orderId
     * @return
     */
    public String getBillNo(String orderId) {
        return new StringBuilder().append(OperateCodeEnum.BILL_NO.getCode()).append(getGeneralId(orderId)).toString();
    }

    /**
     * 获取通用规则id
     * @param uid
     * @return
     */
    private StringBuilder getGeneralId(String uid) {
        StringBuilder id = new StringBuilder();

        int random = (int)((Math.random()*9+1)*1000);
        String uidHashCode = String.valueOf(Math.abs(uid.hashCode() + random));
        uidHashCode = uidHashCode.substring(uidHashCode.length() >= 6 ? uidHashCode.length() - 6 : 0);

        id.append(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli()).append(uidHashCode);
        return id;
    }
}
